{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Pandas 添加列\n\n本教程详细介绍如何在 Pandas DataFrame 中添加新列的各种方法。\n\n## 目录\n1. 直接赋值添加列\n2. 使用 assign() 方法\n3. 使用 insert() 方法\n4. 使用 concat() 添加列\n5. 高级技巧"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 导入库"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\nimport numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. 直接赋值添加列\n\n### 方法说明\n\n最简单的方法是直接给 DataFrame 赋值一个新列。\n\n**语法:**\n```python\ndf['新列名'] = 值\n```\n\n**特点:**\n- ✅ 简单直观\n- ✅ 直接修改原 DataFrame\n- ✅ 支持常量、列表、Series、计算结果\n\n**适用场景:** 快速添加新列"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例1: 创建示例数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.DataFrame({\n    '姓名': ['张三', '李四', '王五'],\n    '年龄': [25, 30, 35]\n})\n\nprint(\"原始 DataFrame:\")\nprint(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例2: 添加常量列\n\n为所有行添加相同的值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df['城市'] = '北京'\nprint(\"添加常量列:\")\nprint(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例3: 添加列表/数组\n\n列表长度必须与 DataFrame 行数相同。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df['工资'] = [8000, 12000, 15000]\nprint(\"添加列表:\")\nprint(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例4: 基于现有列计算\n\n可以对现有列进行运算。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df['年龄_10年后'] = df['年龄'] + 10\nprint(\"基于计算添加列:\")\nprint(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. 使用 assign() 方法\n\n### 方法说明\n\n`assign()` 方法返回一个新的 DataFrame，不修改原数据。\n\n**语法:**\n```python\ndf.assign(新列名=值, ...)\n```\n\n**参数:**\n- 可以同时添加多列\n- 支持 lambda 函数\n- 支持链式调用\n\n**特点:**\n- ✅ 不修改原 DataFrame\n- ✅ 支持链式调用\n- ✅ 函数式编程风格\n- ✅ 可以引用刚创建的列\n\n**适用场景:** 需要保持原数据不变，或使用链式调用时"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例1: 创建示例数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.DataFrame({\n    '姓名': ['Alice', 'Bob', 'Charlie'],\n    '数学': [85, 90, 78],\n    '英语': [92, 88, 95]\n})\n\nprint(\"原始 DataFrame:\")\nprint(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例2: 添加单列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_new = df.assign(总分=df['数学'] + df['英语'])\nprint(\"添加总分列:\")\nprint(df_new)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例3: 同时添加多列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_new = df.assign(\n    总分=df['数学'] + df['英语'],\n    平均分=(df['数学'] + df['英语']) / 2\n)\nprint(\"同时添加多列:\")\nprint(df_new)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例4: 使用 lambda 函数\n\nlambda 函数中的 `x` 代表 DataFrame。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_new = df.assign(\n    总分=lambda x: x['数学'] + x['英语'],\n    平均分=lambda x: x['总分'] / 2\n)\nprint(\"使用 lambda:\")\nprint(df_new)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例5: 链式调用\n\n可以连续调用多个 assign()。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_new = (df\n    .assign(总分=lambda x: x['数学'] + x['英语'])\n    .assign(平均分=lambda x: x['总分'] / 2)\n    .assign(等级=lambda x: pd.cut(x['平均分'], bins=[0, 60, 80, 100], labels=['不及格', '良好', '优秀']))\n)\nprint(\"链式调用:\")\nprint(df_new)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. 使用 insert() 方法\n\n### 方法说明\n\n`insert()` 方法可以在指定位置插入新列。\n\n**语法:**\n```python\ndf.insert(loc, column, value)\n```\n\n**参数:**\n- `loc`: 插入位置（整数索引）\n- `column`: 列名\n- `value`: 列的值\n\n**特点:**\n- ✅ 可以控制列的位置\n- ✅ 直接修改原 DataFrame\n- ❌ 不支持链式调用\n\n**适用场景:** 需要在特定位置插入列时"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例1: 创建示例数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.DataFrame({\n    '姓名': ['张三', '李四', '王五'],\n    '年龄': [25, 30, 35]\n})\n\nprint(\"原始 DataFrame:\")\nprint(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例2: 在指定位置插入列\n\n在位置 1（第二列）插入性别列。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_copy = df.copy()\ndf_copy.insert(1, '性别', ['男', '男', '女'])\nprint(\"在位置1插入列:\")\nprint(df_copy)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例3: 在开头插入列\n\n位置 0 表示第一列。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_copy = df.copy()\ndf_copy.insert(0, 'ID', [1, 2, 3])\nprint(\"在开头插入:\")\nprint(df_copy)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例4: 在末尾插入列\n\n使用 `len(df.columns)` 获取列数，在末尾插入。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_copy = df.copy()\ndf_copy.insert(len(df_copy.columns), '城市', ['北京', '上海', '广州'])\nprint(\"在末尾插入:\")\nprint(df_copy)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. 使用 concat() 添加列\n\n### 方法说明\n\n`concat()` 可以横向拼接 DataFrame 或 Series。\n\n**语法:**\n```python\npd.concat([df, new_col], axis=1)\n```\n\n**参数:**\n- `axis=1`: 横向拼接（列）\n- `axis=0`: 纵向拼接（行）\n\n**特点:**\n- ✅ 可以同时添加多列\n- ✅ 返回新 DataFrame\n- ❌ 相对较慢\n\n**适用场景:** 需要合并多个 Series 或 DataFrame 时"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例: 使用 concat 添加列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.DataFrame({\n    '姓名': ['Alice', 'Bob', 'Charlie'],\n    '年龄': [25, 30, 35]\n})\n\nnew_col = pd.Series(['北京', '上海', '广州'], name='城市')\n\ndf_new = pd.concat([df, new_col], axis=1)\nprint(\"使用 concat 添加列:\")\nprint(df_new)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. 高级技巧\n\n一些实用的添加列技巧。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 技巧1: 条件添加列\n\n使用 `apply()` 或 `lambda` 根据条件添加列。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.DataFrame({\n    '姓名': ['张三', '李四', '王五', '赵六'],\n    '分数': [85, 92, 78, 65]\n})\n\ndf['等级'] = df['分数'].apply(lambda x: '优秀' if x >= 90 else ('良好' if x >= 80 else ('及格' if x >= 60 else '不及格')))\nprint(\"条件添加列:\")\nprint(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 技巧2: 使用 np.where\n\n`np.where()` 是条件赋值的高效方法。\n\n**语法:**\n```python\nnp.where(条件, 真值, 假值)\n```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df['是否及格'] = np.where(df['分数'] >= 60, '及格', '不及格')\nprint(\"使用 np.where:\")\nprint(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 技巧3: 使用 map 映射\n\n`map()` 可以根据字典进行值映射。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.DataFrame({\n    '姓名': ['张三', '李四', '王五'],\n    '部门代码': ['A', 'B', 'A']\n})\n\ndept_map = {'A': '销售部', 'B': '技术部', 'C': '人事部'}\ndf['部门名称'] = df['部门代码'].map(dept_map)\nprint(\"使用 map:\")\nprint(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 总结\n\n### 方法对比\n\n| 方法 | 修改原数据 | 控制位置 | 链式调用 | 适用场景 |\n|------|-----------|---------|---------|----------|\n| 直接赋值 | ✅ | ❌ | ❌ | 快速添加列 |\n| assign() | ❌ | ❌ | ✅ | 函数式编程 |\n| insert() | ✅ | ✅ | ❌ | 控制列顺序 |\n| concat() | ❌ | ❌ | ❌ | 合并多列 |\n\n### 关键要点\n\n1. **直接赋值** 最简单，适合快速添加列\n2. **assign()** 不修改原数据，支持链式调用\n3. **insert()** 可以指定插入位置\n4. **concat()** 适合合并多个 Series\n5. 使用 **np.where** 进行条件赋值效率更高\n6. 使用 **map()** 进行值映射"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.8.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}